import copy
from ZIndex.tool import Util
import random
import pandas as pd
import ZIndexSign as sign
import ZIndex.stock.index as sotckIndex

# index_list = ['KDJ_S','LWR_S','MACD_S','BRAR_S', 'LB_S','VRSI_S','MA_S','BOLL_S','OBV_S','MFI_S']
index_list = ['KDJ_S','WR_S','MACD_S', 'LB_S', 'BOLL_S','OBV_S','MFI_S']

# 从待选指标中不重复抽样5个指标
# 随机指标个数
select_num = len(index_list)
select_index = Util.listRandomChoice(index_list, select_num)


stock = pd.read_csv(r'.\result\ZIndex_Sign.csv', sep=',')
stock_list = stock.drop_duplicates(['code'])
stock_series = stock_list['code']

final_result = pd.DataFrame()
# 获取数据后对数据进行处理
# step 1 按时间进行倒序排列
stock = stock.sort_values(by=['code','date'], ascending=True)
# 默认取最近30天的数据
sign_num = -45
# print(stock)
# step 2 调参
### 参数设置 ###
# KDJ 统计的天数
KDJ_N, KDJ_M1, KDJ_M2 = 9, 3, 3
WR_N, WR_N1, WR_N2 = 14, 6, 3
MACD_MID, MACD_LONG, MACD_SHORT, MACD_LONG2, MACD_LONG3 = 12, 26, 9, 40, 62
BRAR_N = 26
LB_N = 5
MA_N = 5
BOLL_N, BOLL_M = 11, 5
OBV_TimePeriod = 30
MFI_TimePeriod = 14
### 参数设置 end ###


# step 3 计算各指标值
columns = []
# 循环取每个股票stock中数据，计算各日期下的指标变化
def indexSign(stock_code, stock, final_result):
    # 获取股票的数据
    result = stock.loc[stock['code'] == stock_code]
    result = result[['code', 'date', 'open', 'close', 'high', 'low', 'volume', 'amount']]
    result['open'] = result['open'].astype('float')
    result['close'] = result['close'].astype('float')
    result['high'] = result['high'].astype('float')
    result['low'] = result['low'].astype('float')
    result['volume'] = result['volume'].astype('float')
    result['amount'] = result['amount'].astype('float')
    # 用来存储信号结果
    mid_result = result[sign_num:]
    # 获取KDJ指标 返回K D J的值
    K, D, J = sotckIndex.KDJIndex(result, N=KDJ_N, M1=KDJ_M1, M2=KDJ_M2)
    result['K'] = K
    result['D'] = D
    result['J'] = J

    KDJ_sign = sign.KDJ_sign(result[sign_num:])
    mid_result['KDJ_S'] = KDJ_sign.values()

    # 获取WR指标，
    WR = sotckIndex.WR(result, WR_N)
    result['WR'] = WR
    WR_sign = sign.WR_Sign(result[sign_num:])
    mid_result['WR_S'] = WR_sign.values()

    # MACD指标
    macd_dif, macd_dea, macd_macd = sotckIndex.MACD(result, MACD_SHORT, MACD_LONG, MACD_MID)
    result['macd_dif'] = macd_dif
    result['macd_dea'] = macd_dea
    result['macd_macd'] = macd_macd
    MACD_sign = sign.MACD_sign(result)
    mid_result['MACD_S'] = list(MACD_sign.values())[sign_num:]

    # 获取 BRAR-情绪指标，AR, BR VR CY
    BR, AR = sotckIndex.BRAR(result, BRAR_N)
    result['BR'] = BR
    result['AR'] = AR
    #
    # CR1, MA1, MA2, MA3, MA4 = CR(security_list, check_date=check_date, N=MACD_LONG, M1=MACD_SHORT, M2=MACD_MID,
    #                              M3=MACD_LONG2, M4=MACD_LONG3)
    # result['CR'] = CR1.values()
    # result['MA1'] = MA1.values()
    # result['MA2'] = MA2.values()
    # result['MA3'] = MA3.values()
    # result['MA4'] = MA4.values()
    #
    # VR_values, MAVR = VR(security_list, check_date=check_date, N=MACD_LONG, M=MACD_SHORT)
    # result['VR'] = VR_values.values()
    BRAR_sign = sign.BRAR_Sign(result[sign_num:])
    mid_result['BRAR_S'] = BRAR_sign.values()

    # CYR_values, MACYR = CYR(security_list, check_date=check_date, N=CYR_N, M=CYR_M)
    # result['CYR'] = CYR_values.values()
    # result['MACYR'] = MACYR.values()
    # CYR_Sign = sign.CYR_Sign(result)
    # result['CYR_S'] = CYR_Sign.values()

    # 量比指股市开市后平均每分钟的成交量与过去N个交易日平均每分钟成交量之比、
    # 量比0.5成交量萎缩到极致，变盘随时发生。 量比0.8--1.5成交量处于正常水平。量比1.5--2.5温和放量，将会延续原有趋势。
    # 量比2.5--5明显放量，可以采取相应行动了。量比5--10放巨量表现，趋势已到末期。量比>10极端放量，趋势已经到默契，可以考虑反向操作。
    lb = sotckIndex.LB(result, LB_N)
    result['LB'] = lb
    LB_Sign = sign.LB_sign(result[sign_num:])
    mid_result['LB_S'] = LB_Sign.values()

    # MA_N日均线
    MA_values = sotckIndex.MA(result, MA_N)
    result['MA'] = MA_values
    MA_Sign = sign.MA_sign(result[sign_num:])
    mid_result['MA_S'] = MA_Sign.values()

    # 布林通道线BBANDS
    # # MA_Type: 0=SMA, 1=EMA, 2=WMA, 3=DEMA, 4=TEMA, 5=TRIMA, 6=KAMA, 7=MAMA, 8=T3 (Default=SMA)
    upperband, middleband, lowerband = sotckIndex.BBANDS(result, BOLL_M)
    result['upperband'] = upperband
    result['middleband'] = middleband
    result['lowerband'] = lowerband
    BOLL_Sign = sign.BOLL_Sign(result[sign_num:])
    mid_result['BOLL_S'] = BOLL_Sign.values()

    # 3.OBV：能量潮
    OBV_values = sotckIndex.OBV(result)
    # MA_20 = MA(security_list, check_date=check_date, timeperiod=MA_LONG_N)
    amount_20 = sotckIndex.Amount(result, OBV_TimePeriod)
    result['OBV'] = OBV_values
    result['MAVOL2'] = amount_20
    OBV_sign = sign.OBV_sign(result)
    mid_result['OBV_S'] = list(OBV_sign.values())[sign_num:]

    # MFI资金流量指标
    MFI_values = sotckIndex.MFI(result, MFI_TimePeriod)
    result['MFI'] = MFI_values
    MFI_Sign = sign.MFI_sign(result)
    mid_result['MFI_S'] = list(MFI_Sign.values())[sign_num:]

    print("#########")
    print(mid_result)
    # 根据上述指标重新构建sign结果表
    result_select_index = []
    result_select_index = copy.deepcopy(select_index)
    result_select_index.insert(0, 'date')
    result_select_index.insert(1, 'code')
    result_select_index.insert(2, 'close')

    sign_result_df = mid_result.loc[:, result_select_index]

    sign_result_df['sum'] = sign_result_df[select_index].apply(lambda x: x.sum(), axis=1)

    # 统计每支股票信号个数
    print(sign_result_df)
    # stock = pd.concat([stock, sign_result_df], axis=1)

    result_select_index.append('sum')
    columns = result_select_index

    mid_result['sum'] = sign_result_df['sum']

    # print(columns)
    # sign 数据去重，因节假日获取为上一交易日
    # stock = stock.drop_duplicates()

    if final_result.empty:
        final_result = mid_result
    else:
        final_result = final_result.append(mid_result)

    return columns, final_result

topIndexValue = '--'
topIndexDict = {}
topIndexParaDict = {}
weightResult = {}
# 循环10000次修改参数值
for i in range(2):
    # 动态随机生成数 begin
    KDJ_N, KDJ_M1, KDJ_M2 = random.randint(6, 15), random.randint(2, 6), random.randint(2, 6)
    WR_N, WR_N1, WR_N2 = random.randint(10, 18), random.randint(3, 9), random.randint(3, 9)
    MACD_MID, MACD_LONG, MACD_SHORT, MACD_LONG2, MACD_LONG3 = random.randint(8, 16), random.randint(20, 32), \
                                                              random.randint(7, 15), random.randint(30, 50), \
                                                              random.randint(50, 70)
    BRAR_N = random.randint(20, 30)
    LB_N = random.randint(2, 8)
    MA_N = random.randint(2, 8)
    BOLL_N, BOLL_M = random.randint(7, 15), random.randint(2, 8)
    OBV_TimePeriod = random.randint(20, 40)
    MFI_TimePeriod = random.randint(8, 16)
    # 动态随机生成数 end
    for stock_code in security_list:
        columns, final_result = indexSign(stock_code, stock, final_result)

    # 去掉重复数据
    final_result = final_result.drop_duplicates()
    # 排序，按时间来排序
    final_result = final_result.sort_values(by=['date', 'code'], ascending=False)
    # Util.dataFrameToCsv(final_result, "/result/BaoSign_all.csv", True)

    Util.dataFrameToCsv(final_result, "/result/AutoBaoSign.csv", True, columns=columns)

    result_select_index = copy.deepcopy(select_index)
    result_select_index.insert(0, 'date')
    result_select_index.insert(1, 'code')
    result_select_index.insert(2, 'close')

    sign_result_df = final_result.loc[:, result_select_index]
    tempSign = copy.deepcopy(sign_result_df)

    finalResult = pd.DataFrame()

    acc_name_list = ['code']
    # 计算每一组的平均准确率
    for column in index_list:
        # print(column)
        index_name = column
        acc_name = index_name + '_acc'
        acc_name_list.append(acc_name)
        for index, value in stock_series.items():
            tempSign[acc_name] = 0
            finalResult = sign.index_acc(index, index_name, acc_name, tempSign, value)

    Util.dataFrameToCsv(finalResult.loc[:, acc_name_list], "/result/AutoBaoSign_acc_all.csv", True, True)
    data = ' KDJ_S_acc-KDJ_N:' + str(KDJ_N) + ', KDJ_S_acc-KDJ_M1:' + str(KDJ_M1) + ', KDJ_S_acc-KDJ_M2:' + str(KDJ_M2)  + ', WR_S_acc-WR_N:' + str(WR_N)\
           + ', WR_S_acc-WR_N1:' + str(WR_N1)  + ', WR_S_acc-WR_N2:' + str(WR_N2)  + ', MACD_S_acc-MACD_MID:' + str(MACD_MID)  + ', MACD_LONG:' + str(MACD_LONG)  \
           + ', MACD_S_acc-MACD_SHORT:' + str(MACD_SHORT)  + ', MACD_S_acc-MACD_LONG2:' + str(MACD_LONG2)  + ', MACD_S_acc-MACD_LONG3:' + str(MACD_LONG3) \
           + ', BRAR_S_acc-BRAR_N:' + str(BRAR_N)  + ', LB_S_acc-LB_N:' + str(LB_N)  + ', MFI_S_acc-MFI_TimePeriod:' + str(MFI_TimePeriod)\
           + ', MA_S_acc_MA_N:' + str(MA_N)+ ', BOLL_S_acc-BOLL_N:' + str(BOLL_N)  + ', BOLL_S_acc-BOLL_M:' + str(BOLL_M)  + ', OBV_S_acc-OBV_TimePeriod:' + str(OBV_TimePeriod)


    Util.dataToTxt(data, '/result/AutoBaoSign_acc_all.csv', True)

    # 记录每个指标准确率最高时对应的值
    for index_name in finalResult.columns:
        index_acc_sum = 0
        # 存在准确率值时
        if index_name.find('acc')>=0:
            # index_acc_sum = round(finalResult[index_name].sum() / finalResult.shape[0], 2)
            index_acc_sum = round(finalResult[index_name].sum() / len(finalResult[finalResult[index_name] != 0]), 2)
            if index_name in topIndexDict:
                if index_acc_sum > topIndexDict[index_name]:
                    topIndexDict[index_name] = index_acc_sum
                    topIndexParaDict[index_name] = Util.strSub(data, ',', index_name)
            else:
                topIndexDict[index_name] = index_acc_sum
                topIndexParaDict[index_name] = Util.strSub(data, ',', index_name)





print("### 各指标最高准确率为 #####")
print(topIndexDict)
Util.dataToTxt("各指标最高准确率为", '/result/AutoBaoSign_acc.txt', True)
Util.dataToTxt(str(topIndexDict), '/result/AutoBaoSign_acc.txt', True)
## 根据指标最高准确率计算权重
weightResult = copy.deepcopy(topIndexDict)
# 去掉sum_acc
del weightResult['sum_acc']
weight_all = sum(weightResult.values())
for i, index in enumerate(weightResult):
    weightResult[index] = round(weightResult[index] / weight_all, 3)
print("###各指标权重###")
print(weightResult)
Util.dataToTxt("各指标对应权重为", '/result/AutoBaoSign_acc.txt', True)
Util.dataToTxt(str(weightResult), '/result/AutoBaoSign_acc.txt', True)

print("### 各指标最高准确率对应参数值为 #####")
print(topIndexParaDict)
Util.dataToTxt("各指标最高准确率对应参数值为", '/result/AutoBaoSign_acc.txt', True)
Util.dataToTxt(str(topIndexParaDict), '/result/AutoBaoSign_acc.txt', True)

## 根据获取到的最优参数值来计算最近一日指标准确率
# 暂时分成两步，去Baostock_main方法执行









